package com.china.produce.system.util;

import com.china.produce.annotation.LoginNeedless;
import com.china.produce.pojo.CurrentUserInfo;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.method.HandlerMethod;

@Component
public class LoginUtils {
    private static final Logger log = LoggerFactory.getLogger(LoginUtils.class);
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Value("${spring.redis.key.prefix}")
    private String redisKeyPrefix;
    public static RedisTemplate<String, Object> REDIS_TEMPLATE;
    public static String REDIS_KEY_PREFIX;
    private static final String LOGIN_MOBILE = "LOGIN_MOBILE";
    private static final String LOGIN_ACCOUNT_ID = "LOGIN_ACCOUNT_ID";
    private static final String LOGIN_KEY = "SCRM_LOGIN_KEY_%s";
    public static final String APP_USER_NAME = "APP_USER_NAME:";
    public static final String APP_REQ_TOKEN = "APP_REQ_TOKEN:";
    private static final ThreadLocal<CurrentUserInfo> currentUser = new InheritableThreadLocal();
    private static final ThreadLocal<HttpSession> SESSION = new InheritableThreadLocal();

    public LoginUtils() {
    }

    @PostConstruct
    public void init() {
        log.info("Initialize LoginUtils: {}, {}", this.redisKeyPrefix, this.redisTemplate);
        REDIS_TEMPLATE = this.redisTemplate;
        REDIS_KEY_PREFIX = this.redisKeyPrefix;
    }

    public static void setCurrentUser(CurrentUserInfo user) {
        currentUser.set(user);
    }

    public static CurrentUserInfo getCurrentUser() {
        return (CurrentUserInfo)currentUser.get();
    }

    public static Long getCurrentUserId() {
        CurrentUserInfo loginUser = (CurrentUserInfo)currentUser.get();
        return loginUser != null ? loginUser.getId() : null;
    }

    public static String getCurrentUserCorpId() {
        CurrentUserInfo loginUser = (CurrentUserInfo)currentUser.get();
        return loginUser != null ? loginUser.getCorpId() : null;
    }

    public static Long getCurrentUserBizId() {
        CurrentUserInfo loginUser = (CurrentUserInfo)currentUser.get();
        return loginUser != null ? loginUser.getBizId() : null;
    }

    public static void setSession(HttpSession httpSession) {
        SESSION.set(httpSession);
    }

    public static HttpSession getSession() {
        ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        return attributes == null ? (HttpSession)SESSION.get() : attributes.getRequest().getSession();
    }

    public static void clear() {
        currentUser.remove();
        SESSION.remove();
    }

    public static String getUserInfoKey(String redisKeyPrefix, Long userId) {
        return redisKeyPrefix + getSessionId() + String.format("SCRM_LOGIN_KEY_%s", userId);
    }

    public static void initCurrentUser(RedisTemplate<String, Object> redisTemplate, String redisKeyPrefix) {
        String key = getUserInfoKey(redisKeyPrefix, getLoginAccountId());
        Object cache = redisTemplate.opsForValue().get(key);
        if (cache != null) {
            if (cache instanceof CurrentUserInfo) {
                setCurrentUser((CurrentUserInfo)cache);
            } else {
                log.error("The user is not front system.");
            }
        }

        redisTemplate.opsForValue().set(getSessionId(), getLoginAccountId());
    }

    public static void initRpcCurrentUser(String sessionId, Long userId) {
        String key = getUserInfoKey(REDIS_KEY_PREFIX, sessionId, userId);
        Object cache = REDIS_TEMPLATE.opsForValue().get(key);
        if (cache != null) {
            if (cache instanceof CurrentUserInfo) {
                setCurrentUser((CurrentUserInfo)cache);
            } else {
                log.error("The user is not front system.");
            }
        }

    }

    private static String getUserInfoKey(String redisKeyPrefix, String sessionId, Long userId) {
        return redisKeyPrefix + sessionId + String.format("SCRM_LOGIN_KEY_%s", userId);
    }

    public static void deleteCurrentUser(RedisTemplate<String, Object> redisTemplate, String redisKeyPrefix) {
        String key = getUserInfoKey(redisKeyPrefix, getLoginAccountId());
        redisTemplate.delete(key);
    }

    public static boolean hasLoginNeedless(Object handler) {
        if (!(handler instanceof HandlerMethod)) {
            return false;
        } else {
            HandlerMethod handlerMethod = (HandlerMethod)handler;
            Class<?> type = handlerMethod.getBeanType();
            LoginNeedless loginNeedless = (LoginNeedless)type.getAnnotation(LoginNeedless.class);
            if (loginNeedless == null) {
                loginNeedless = (LoginNeedless)type.getSuperclass().getAnnotation(LoginNeedless.class);
            }

            if (loginNeedless == null) {
                loginNeedless = (LoginNeedless)handlerMethod.getMethodAnnotation(LoginNeedless.class);
            }

            return loginNeedless != null;
        }
    }

    public static String getSessionId() {
        HttpSession session = getSession();
        return session != null ? session.getId() : null;
    }

    public static Long getLoginAccountId() {
        Long userId = null;
        HttpSession session = getSession();
        if (session != null) {
            userId = (Long)session.getAttribute("LOGIN_ACCOUNT_ID");
        }

        return userId;
    }

    public static void setLoginAccountId(Long userId) {
        HttpSession session = getSession();
        if (session != null) {
            session.setAttribute("LOGIN_ACCOUNT_ID", userId);
        }

    }

    public static void removeLoginAccountId() {
        HttpSession session = getSession();
        if (session != null) {
            session.removeAttribute("LOGIN_ACCOUNT_ID");
            session.removeAttribute("LOGIN_MOBILE");
        }

    }

    public static void setLoginMobile(String mobile) {
        HttpSession session = getSession();
        if (session != null) {
            session.setAttribute("LOGIN_MOBILE", mobile);
        }

    }

    public static String getLoginMobile() {
        String mobile = null;
        HttpSession session = getSession();
        if (session != null) {
            mobile = (String)session.getAttribute("LOGIN_MOBILE");
        }

        return mobile;
    }

    public static String buildAppUserNameKey(String redisKeyPrefix, String username) {
        return redisKeyPrefix + "APP_USER_NAME:" + username;
    }

    public static String buildAppReqTokenKey(String redisKeyPrefix, String reqToken) {
        return redisKeyPrefix + "APP_REQ_TOKEN:" + reqToken;
    }
}
